/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.leinardi.ohos.speeddial;

import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorProperty;
import ohos.agp.components.*;
import ohos.agp.utils.LayoutAlignment;
import ohos.app.Context;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;

/**
 * 封装一个简单的SnackBar
 */
public class SnackBar extends StackLayout {
    private static final int DURATION = 150;

    public static final int LENGTH_SHORT = -1;
    public static final int LENGTH_LONG = -2;
    public static final int LENGTH_INDEFINITE = -3;

    private static int DEFAULT_SHOW_TIME_MS = 3000;

    private Text mText;
    private Button mActionButton;

    private EventHandler mHandler;

    private final Runnable mCloseRunnable = () -> close(true);

    public SnackBar(Context context) {
        super(context);
        initWithContext(context);
    }

    public SnackBar(Context context, AttrSet attrSet) {
        super(context, attrSet);
        initWithContext(context);
    }

    public SnackBar(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
        initWithContext(context);
    }

    private void initWithContext(Context context) {
        mHandler = new EventHandler(EventRunner.getMainEventRunner());

        LayoutScatter.getInstance(context).parse(ResourceTable.Layout_snackbar_layout, this, true);
        mText = (Text)findComponentById(ResourceTable.Id_text);
        mActionButton = (Button)findComponentById(ResourceTable.Id_snackbar_action);

        mText.setTruncationMode(Text.TruncationMode.ELLIPSIS_AT_END);
    }

    public void setMessage(String message) {
        mText.setText(message);
    }

    public void setActionListener(String text, ClickedListener listener) {
        mActionButton.setText(text);
        mActionButton.setClickedListener(listener);
    }

    public void setDuration(int duration) {
        if(duration > 0) {
            if(duration < 1500) {
                throw new IllegalArgumentException("Min duration is 1500ms");
            }
            DEFAULT_SHOW_TIME_MS = duration;
        }else {
            switch (duration) {
                case LENGTH_SHORT:
                    DEFAULT_SHOW_TIME_MS = 3000;
                    break;
                case LENGTH_LONG:
                    DEFAULT_SHOW_TIME_MS = 5000;
                    break;
                case LENGTH_INDEFINITE:
                    DEFAULT_SHOW_TIME_MS = Integer.MAX_VALUE;
                    break;
                default:
                    break;
            }
        }
    }

    public void show() {
        setVisibility(VISIBLE);
        AnimatorProperty property = new AnimatorProperty(this);
        property.alphaFrom(0.0f).alpha(1.0f);
        property.scaleXFrom(0.5f).scaleX(1.0f);
        property.scaleYFrom(0.0f).scaleY(1.0f);
        property.setDuration(DURATION);
        property.setCurveType(Animator.CurveType.LINEAR);
        property.start();

        //自动消失
        autoClose();
    }

    public void close(boolean isAnim) {
        if(getVisibility() == VISIBLE) {
            if(isAnim) {
                AnimatorProperty property = new AnimatorProperty(this);
                property.alphaFrom(1.0f).alpha(0.0f);
                property.scaleXFrom(1.0f).scaleX(0.5f);
                property.scaleYFrom(1.0f).scaleY(0.0f);
                property.setDuration(DURATION);
                property.setCurveType(Animator.CurveType.LINEAR);
                property.setStateChangedListener(new AnimStateChangedListener(){
                    @Override
                    public void onEnd(Animator animator) {
                        SnackBar.this.getComponentParent().removeComponent(SnackBar.this);
                    }
                });
                property.start();
            }else {
                if(getComponentParent() != null) {
                    getComponentParent().removeComponent(this);
                }
            }
        }
        //移除mCloseRunnable
        mHandler.removeTask(mCloseRunnable);
    }

    private void autoClose() {
        if(DEFAULT_SHOW_TIME_MS != Integer.MAX_VALUE) {
            mHandler.postTask(mCloseRunnable, DEFAULT_SHOW_TIME_MS);
        }
    }

    public static SnackBar make(Component component, String text, int duration) {
        SnackBar snackBar = new SnackBar(component.getContext());
        if(component instanceof DirectionalLayout) {
            DirectionalLayout parent = (DirectionalLayout)component;
            DirectionalLayout.LayoutConfig layoutConfig = new DirectionalLayout.LayoutConfig(
                    DirectionalLayout.LayoutConfig.MATCH_PARENT, DirectionalLayout.LayoutConfig.MATCH_CONTENT);
            layoutConfig.alignment = LayoutAlignment.BOTTOM;
            int margin = AttrHelper.fp2px(10f, component.getContext());
            layoutConfig.setMargins(margin, margin, margin, margin);
            parent.addComponent(snackBar, layoutConfig);
        }else if(component instanceof DependentLayout) {
            DependentLayout parent = (DependentLayout)component;
            DependentLayout.LayoutConfig layoutConfig = new DependentLayout.LayoutConfig(
                    DependentLayout.LayoutConfig.MATCH_PARENT, DependentLayout.LayoutConfig.MATCH_CONTENT);
            layoutConfig.addRule(DependentLayout.LayoutConfig.ALIGN_BOTTOM);
            int margin = AttrHelper.fp2px(10f, component.getContext());
            layoutConfig.setMargins(margin, margin, margin, margin);
            parent.addComponent(snackBar, layoutConfig);
        }else if(component instanceof StackLayout) {
            StackLayout parent = (StackLayout)component;
            StackLayout.LayoutConfig layoutConfig = new StackLayout.LayoutConfig(
                    StackLayout.LayoutConfig.MATCH_PARENT, StackLayout.LayoutConfig.MATCH_CONTENT);
            layoutConfig.alignment = LayoutAlignment.BOTTOM;
            int margin = AttrHelper.fp2px(10f, component.getContext());
            layoutConfig.setMargins(margin, margin, margin, margin);
            parent.addComponent(snackBar, layoutConfig);
        }else if(component instanceof ComponentContainer) {
            ComponentContainer parent = (ComponentContainer)component;
            ComponentContainer.LayoutConfig layoutConfig = new ComponentContainer.LayoutConfig(
                    ComponentContainer.LayoutConfig.MATCH_PARENT, ComponentContainer.LayoutConfig.MATCH_CONTENT);
            int margin = AttrHelper.fp2px(10f, component.getContext());
            layoutConfig.setMargins(margin, margin, margin, margin);
            parent.addComponent(snackBar, layoutConfig);
        }
        snackBar.setMessage(text);
        snackBar.setDuration(duration);
        return snackBar;
    }

}
